package ru.ifmo.ctd.year2008.notepad.diff;

import ru.ifmo.ctd.year2008.notepad.Line;
import ru.ifmo.ctd.year2008.notepad.Text;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class Diff implements Serializable {
	private static final long serialVersionUID = 3792615306806679555L;
	
	public static final long FIRST_LINE = Long.MIN_VALUE;
    private final List<Line> originalText;
    private final List<Line> modifiedText;
    private final long afterWhatLineToApply;   //FIRST_LINE if first line

    public Diff(List<Line> originalText, List<Line> modifiedText, long afterWhatLineToApply) {
        this.originalText = originalText;
        this.modifiedText = modifiedText;
        this.afterWhatLineToApply = afterWhatLineToApply;
    }

    public Text apply(Text text) {
        List<Line> lines = text.getLines();
        int position = getPosition(lines, afterWhatLineToApply);
        if (position < 0) {
            return null;
        }
        if (position + originalText.size() > lines.size()) {
            return null;
        }
        for (int i = 0; i < originalText.size(); i++) {
            Line expectedLine = originalText.get(i);
            Line haveLine = lines.get(position + i);
            if (expectedLine.getId() != haveLine.getId()) {
                return null;
            }
        }
        lines = new ArrayList<Line>(lines);
        lines.subList(position, position + originalText.size()).clear();

        for (int i = 0; i < modifiedText.size(); i++) {
            if (getPosition(lines, modifiedText.get(i).getId()) >= 0) {
                return null;
            }
        }

        lines.addAll(position, modifiedText);
        return new Text(lines);
    }

    private static int getPosition(List<Line> lines, long id) {
        if (id == FIRST_LINE) {
            return 0;
        }
        for (int i = 0; i < lines.size(); i++) {
            if (lines.get(i).getId() == id) {
                return i + 1;
            }
        }
        return -1;
    }

    @Override
    public String toString() {
        return "Diff{" +
                "originalText=" + originalText +
                ", modifiedText=" + modifiedText +
                ", afterWhatLineToApply=" + afterWhatLineToApply +
                '}';
    }
}
